feat(core): add renderCopyButton render prop to CodeBlock - #4795
feat(core): add renderCopyButton render prop to CodeBlock#4795freddymeta wants to merge 1 commit into
Conversation
CodeBlock's copy control was a bare, unstyleable <button> with no way to replace it — the component exposed only the root theme target, so consumers who needed a different copy control (e.g. one with a tooltip) had to disable hasCopyButton and re-implement placement, clipboard, and copied-state themselves. Add a renderCopyButton render prop: the block keeps ownership of placement (header, or floating corner when headerless), the clipboard write, the copied-state timer, and the polite copy announcement; the render prop only supplies the visual control, wired to copy/isCopied/label. Ignored when hasCopyButton is false.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR Analysis Report📚 Storybook PreviewView Storybook for this PR 🧪 Sandbox PreviewView Sandbox for this PR Modified ComponentsCodeBlock (@astryxdesign/core) · View in Storybook
Bundle Size Summary
Accessibility AuditStatus: No accessibility violations detected. Generated by PR Enrichment workflow | Storybook | Sandbox | View full report |
|
Closing — wrong shape for the actual need. The goal was to upstream CodeBlock's copy button so consumers stop re-implementing it (bare The right fix is to improve CodeBlock's own copy button — a default "Copy"/"Copied" tooltip and a theme target so it's restyleable — backed by an extracted |
What this does
Adds a
renderCopyButtonrender prop toCodeBlock, letting a consumer supply its own copy control whileCodeBlockkeeps ownership of everything that isn't the button's appearance.Why
CodeBlock's copy control is a bare<button>with no tooltip, and there's no seam to restyle or replace it:hasCopyButtonis a plain boolean, and the component exposes a single theme target on the root<pre>. A design system consuming Astryx that wants its own copy control (e.g. its standard icon button with a "Copy" tooltip — a tooltip is DOM, so it can't be added via theming or CSS) is forced to sethasCopyButton={false}and then re-implement placement, the clipboard write, the copied-state timer, and the copy announcement, plus position the replacement with structural CSS against internal DOM. That's the "reach for an unsupported structural selector" signal that a sanctioned seam is missing.A paint/theme target is the wrong tier here (the need is a different control, not different paint on the same one), and an imperative
copy()ref was considered previously and set aside. A render prop is the right shape — it mirrors the existingrenderOption/renderItem/renderTokenconvention and hands back exactly the state a copy control needs.The seam
CodeBlockstill owns:onCopy.The render prop only supplies the visual control. Ignored when
hasCopyButtonisfalse.Scope
Additive and backward-compatible — the built-in button path is unchanged when
renderCopyButtonis omitted. No new theme target, no DOM change to existing usage.Tests
Extended
CodeBlock.test.tsxwith arenderCopyButtonblock: custom control replaces the built-in button,copy/isCopied/labeldrive the block's clipboard + copied flow, the announcement andonCopystill fire,hasCopyButton={false}suppresses it, and the custom control stays out of the collapsible header'srole="button".22/22CodeBlock tests, core typecheck, storybook typecheck, docsite (324), and strict lint all green. Added aCustomCopyButtonStorybook story.